package com.arpa.wms.service;

import com.arpa.core.web.Result;
import com.arpa.wms.domain.dto.InventoryDTO;
import com.arpa.wms.domain.entity.*;
import com.arpa.wms.domain.vo.InventoryImportVO;
import com.arpa.wms.domain.vo.InventoryVO;
import com.arpa.wms.domain.vo.InventoryWithDistributionVO;
import com.arpa.wms.domain.vo.UsefulInventoryVO;
import com.baomidou.mybatisplus.extension.service.IService;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 库存 服务类
 * </p>
 *
 * @author LEO
 * @since 2020-08-04
 */
public interface IInventoryService extends IService<Inventory> {

    /**
     * 保存
     * @param entity
     * @return
     */
    @Override
    boolean save(Inventory entity);

    /**
     * 根据code更新实体
     * @param entity
     * @return
     */
    int updateByCode(Inventory entity);

    /**
     * 查询列表
     * @param inventoryDTO
     * @return
     */
    List<InventoryVO> queryList(InventoryDTO inventoryDTO);

    /**
     * 查询汇总数量
     * @param inventoryDTO
     * @return
     */
    InventoryVO querySumQuantity(InventoryDTO inventoryDTO);

     /**
      *  @author: Allen chen
      *  @Date: 2020/10/28 14:22
      *  @Description: 条件插叙  不带分页
      */
    List<InventoryVO> queryByCondition(InventoryDTO inventoryDTO);

     /**
      *  @author: Allen chen
      *  @Date: 2020/9/30 9:20
      *  @Description: 根据库存状态查询库存列表
      */
    List<InventoryVO> queryByInventoryStatus(List<String> statusList);

    /**
     * 查询合计,包含总数
     * @param inventoryDTO
     * @return
     */
    InventoryVO queryListSum(InventoryDTO inventoryDTO);

    /**
     * 锁库存
     * @param code
     */
    void lock(String code);

    /**
     * 解锁库存
     * @param code
     */
    void unlock(String code);

    /**
     * 批次调整
     * @param inventoryDTO
     * @return
     */
    Result lotAdjust(InventoryDTO inventoryDTO);

    /**
     * 查询可移位库存
     * @param inventoryDTO
     * @return
     */
    List<InventoryVO> queryCanMoveList(InventoryDTO inventoryDTO);

    InventoryVO queryCanMoveListSum(InventoryDTO inventoryDTO);

    InventoryVO getOneByCode(String code);

    List<InventoryWithDistributionVO> queryCanDistributeInventory(String warehouseCode, String shipmentCode, String goodsCode);

    /**
     * 根据库存code锁定部分库存数量
     * @param code
     * @param distributionQuantity
     * @return
     */
    Result lockInventory(String code, BigDecimal distributionQuantity);

    /**
     * 获取可以自动分配的库存
     * @param inventoryDTO
     * @return
     */
    List<UsefulInventoryVO> getCanAutoDistributedInventory(InventoryDTO inventoryDTO,Integer isDeliveringIfStockout);

    /**
     * 判断是否有相同的库存，并返回该库存信息
     * @param lot
     * @param goodsCode
     * @param location
     * @param shipmentCode
     * @param goodsStatus
     * @param isLock
     * @return
     */
    Inventory hasSameInventory(String lot, String goodsCode, String location, String shipmentCode, String goodsStatus,
                               Integer isLock, String containerBarCode, LocalDateTime gmtStock);


    /**
     * 判断是否有相同的库存，并返回该库存信息
     * @param lot
     * @param goodsCode
     * @param location
     * @param shipmentCode
     * @param goodsStatus
     * @param isLock
     * @return
     */
    Inventory hasSameInventoryQc(String lot, String goodsCode, String location, String shipmentCode, String goodsStatus,
                               Integer isLock);

    /**
     * 判断是否有相同的收货临时库存
     * @param receiveRegister
     * @param receive
     * @return
     */
    Inventory hasSameReceiveTempInventory(ReceiveRegister receiveRegister, Receive receive);

    /**
     * 创建收货临时库位库存
     * @param receiveRegister
     * @param receive
     * @param receiveItem
     * @return
     */
    Inventory saveReceiveTempInventory(ReceiveRegister receiveRegister, Receive receive, ReceiveItem receiveItem);

    /**
     * 创建出货临时库存
     * @param distribution
     * @param delivery
     * @param deliveryItem
     * @param inventory
     * @return
     */
    Inventory saveDeliveryTempInventory(DeliveryDistribution distribution, Delivery delivery, DeliveryItem deliveryItem, Inventory inventory);

    /**
     * 判断是否有相同的发货临时库存
     * @param distribution
     * @param delivery
     * @return
     */
    Inventory hasSameDeliveryTempInventory(DeliveryDistribution distribution, Delivery delivery);

    /**
     * 取消分配、缺货时返还库存
     * @param tempInventory
     * @param returnQuantity
     * @return
     */
    Result returnInventory(Inventory tempInventory, BigDecimal returnQuantity);

    /**
     * @description
     * 缺货登记时返还库存
     * @author xuyang
     * @date 2020/10/23 10:02
     * @param inventoryCode: 操作的临时库存
     * @param stockoutQuantity: 缺货数量（返还数量）
     * @param type:  操作类型
     * @param sourceCode:  操作单据号
     **/
    Result stockoutInventory(String inventoryCode, BigDecimal stockoutQuantity, String type, String sourceCode);

    /**
     * 库存存储托盘数量
     * @param code 库位code
     * @return
     */
    Integer countPallet(String code);

    /**
     * 更新库存数量，正数为增加库存，负数为减少库存
     * @param inventoryCode
     * @param adjustQuantity
     * @return
     */
    boolean adjustQuantity(String inventoryCode, BigDecimal adjustQuantity);

    /**
     * 减少库存
     * @author liuxr
     * @date 2021/12/6 17:37
     * @param inventoryCode
     * @param adjustQuantity
     * @return boolean
     */
    boolean reduceQuantity(String inventoryCode, BigDecimal adjustQuantity);

    /**
     * 增加库存
     * @author liuxr
     * @date 2021/12/6 17:37
     * @param inventoryCode
     * @param adjustQuantity
     * @return boolean
     */
    boolean addQuantity(String inventoryCode, BigDecimal adjustQuantity);

    /**
     * 更新占用库存数量，正数为增加库存，负数为减少库存
     * @param inventoryCode
     * @param adjustQuantity
     * @return
     */
    boolean adjustUsedQuantity(String inventoryCode, BigDecimal adjustQuantity);
     /**
      *  @author: Allen chen
      *  @Date: 2020/11/5 18:05
      *  @Description:更新总库存和占用库存 正数加，负数减
      */
    boolean adjustQuantityAndUseQuantity(String inventoryCode, BigDecimal adjustQuantity,BigDecimal adjustUseQuantity);

    /**
     * @description
     * 判断库存中是否有使用该容器号的库存
     * @author xuyang
     * @date 2020/10/29 14:23
     * @param containerBarCode:
     **/
    boolean noUseContainerBarCode(String containerBarCode);

    /**
     * @description
     * 将临时库存作业状态设为工作中
     * @author xuyang
     * @date 2020/10/31 9:31
     * @param tempInvCode:
     **/
    Result setTempInvJobStatusWorking(String tempInvCode);

    /**
     * @description
     * 将库存（临时库存）作业状态改为正常，条件是，临时库存全部被释放了
     * @author xuyang
     * @date 2020/10/31 9:31
     * @param tempInvCode:
     **/
    Result releaseEmptyTempInvJobStatus(String tempInvCode);

    /**
     * @description
     * 将库存（临时库存）作业状态改为正常，用于拣货确认后的操作
     * @author xuyang
     * @date 2020/10/31 9:31
     * @param tempInvCode:
     **/
    Result releaseTempInvJobStatus(String tempInvCode);

    /**
     * 判断仓库下是否有库存
     * @param warehouseCode
     * @return
     */
    boolean warehouseHasInv(String warehouseCode);

    /**
     * 根据条件查询库存总量
     * @param inventoryDTO
     * @return
     */
    BigDecimal queryInventorySum(InventoryDTO inventoryDTO);


    /**
     * 获取仓库库存
     * @param warehouseCodes 仓库code
     * @return  Map.key="quatity","warehouseCode"
     */
    List<Map<String,Object>> getQuantity(List<String> warehouseCodes);

    /**
     * 锁可用库存
     * @param warehouseCode
     * @param goodsCode
     * @param goodsName
     * @param shipmentCode
     * @param lockQuantity
     */
    void lockUsefulInventory(String warehouseCode, String goodsCode, String goodsName, String shipmentCode, BigDecimal lockQuantity);

    /**
     * 计算不可用库存数量；不可用库存是指库存状态为不可发货的库存；
     * @param inventoryDTO
     * @return
     */
    BigDecimal countUnusableInv(InventoryDTO inventoryDTO);

    /**
     * 更新oms不可用库存数量，进一步封装countUnusableInv方法
     * @param inventoryDTO
     */
    void updateOmsContUseQuantity(InventoryDTO inventoryDTO);

    /**
     * 更新oms不可用库存数量，进一步封装countUnusableInv方法
     * @param warehouseCode
     * @param shipmentCode
     * @param goodsCode
     */
    void updateOmsContUseQuantity(String warehouseCode, String shipmentCode, String goodsCode);

    /**
     * 根据货主、库存状态值获取不可用库存信息，包括仓库、商品、不可用数量；用于更新oms不可用库存数量
     * @param inventoryDTO
     * @return
     */
    List<InventoryVO> getContUseQuantityInfo(InventoryDTO inventoryDTO);

    /**
     * 执行原生sql
     * @param sql
     */
    void execSql(String sql);

    /**
     * 获取推荐库位
     * @param inventoryDTO
     */
    List<InventoryVO> getRecommondLocation(InventoryDTO inventoryDTO);




    /**
     * 判断是否有相同的预打包临时库存
     * @param distribution
     * @return
     */
    Inventory hasSamePrepackagedTempInventory(PrepackagedDistribution distribution);

    /**
     * 创建预打包临时库存
     * @param distribution
     * @param prepackaged
     * @param oldInventory
     * @return
     */
    Inventory savePrepackagedTempInventory(PrepackagedDistribution distribution, Prepackaged prepackaged,Inventory oldInventory);








    List<InventoryImportVO> importInventory(InventoryDTO inventoryDTO);

    /**
     * 查询导入单合计,包含总数
     * @param inventoryDTO
     * @return
     */
    InventoryImportVO importInventorySum(InventoryDTO inventoryDTO);


    /**
     * 创建预打包临时库存
     * @param receiveRegisterList
     * @param receiveItems
     * @param receive
     * @return
     */
    List<Inventory> batchGenReceiveTempInventory(List<ReceiveRegister> receiveRegisterList,List<ReceiveItem> receiveItems,Receive receive);


}
